<?php

namespace App\Library;


use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Picqer\Barcode\BarcodeGeneratorPNG;

class Common
{


    public static function cdnurl($url, $domain = false)
    {

        $regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
        $cdn = env('CDNURL', config('upload.cdnurl'));
        $url = preg_match($regex, $url) ? $url : $cdn . $url;
        if ($domain && !preg_match($regex, $url)) {
            $domain = is_bool($domain) ? '' : $domain;
            $url = $domain . $url;
        }
        return $url;
    }
    public static function cdnurl2($url, $domain = false)
    {

        $regex = "/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i";
        $cdn = env('CDNURL2', 'https://oss.gongfuc.com');
        $url = preg_match($regex, $url) ? $url : $cdn . $url;
        if ($domain && !preg_match($regex, $url)) {
            $domain = is_bool($domain) ? '' : $domain;
            $url = $domain . $url;
        }
        return $url;
    }

    /**
     * 检查阶梯价是否合理
     * @param array $step_price 阶梯价数组
     * @return bool
     */
    public static function check_step_price($step_price): bool
    {
        if (count($step_price) > 0) {
            $num_list = $price_list = [];
            $num_list = array_column($step_price, 'price', 'num');
            $price_list = array_column($step_price, 'num', 'price');
//        数组中有重复值？
            if (array_unique($num_list) != $num_list || array_unique($price_list) != $price_list) {
                return false;
            }
            ksort($num_list);
            krsort($price_list);
//            这里翻转会变int，对比失效 所以对调两次统一
            $price_list = array_flip($price_list);
            $num_list = array_flip(array_flip($num_list));
            if ($price_list !== $num_list) {
                return false;
            }
        }
        return true;
    }

    /**
     * 获取条形码信息
     * @param string $msg
     * @return string
     */
    public static function get_bar_code($msg = '')
    {
        if (empty($msg)) {
            return $msg;
        }
        $generator = new BarcodeGeneratorPNG();
        $code = $generator->getBarcode($msg, $generator::TYPE_CODE_128, 1);
        return "data:image/png;base64," . base64_encode($code);
    }

    public static function reloadRoute()
    {
        $path = BASE_PATH . '/config/routes';
        $dirs = scandir($path);

        foreach ($dirs as $dir) {
            if ($dir != '.' && $dir != '..') {
                $routeFilePath = $path . "/{$dir}";
                require_once $routeFilePath;
            }
        }
    }

    /**
     * 过滤数组空值
     * @param array $params
     * @return array
     */
    public static function filter_null(array $params)
    {
        return array_filter($params, function ($fields) {
            if ($fields === '' || $fields === null) {
                return false;
            }
            return true;
        });
    }

    /**
     *计算两个日期的差值
     * @param $date1
     * @param $data2
     * @return string
     */
    public static function diff_data($date1, $data2)
    {
        $date1 = date_create($date1);
        $date2 = date_create($data2);
        $interval = date_diff($date1, $date2);
        return $interval->format('%R%a');
    }

    /**
     *返回当前时间的日期或日期时间
     * @param $type
     * @param $time
     * @return string
     */
    public static function date_time($type = 1, $time = '')
    {
        if ($time == '') {
            $time = time();
        }
        if ($type == 1) {
            return date('Y-m-d', $time);
        } else {
            return date('Y-m-d H:i:s', $time);
        }
    }

    /**
     * 过滤数组空值
     * @param string $end
     * @param string $begin
     * @param string $str
     * @return string
     */
    public static function cut($begin, $end, $str)
    {

        $b = mb_strpos($str, $begin) + mb_strlen($begin);

        $e = mb_strpos($str, $end) - $b;

        return mb_substr($str, $b, $e);

    }

    /**
     * 首字母头像
     * @param $text
     * @return string
     */
    public static function letter_avatar($text)
    {
        $total = unpack('L', hash('adler32', $text, true))[1];
        $hue = $total % 360;
        list($r, $g, $b) = self::hsv2rgb($hue / 360, 0.3, 0.9);

        $bg = "rgb({$r},{$g},{$b})";
        $color = "#ffffff";
        $first = mb_strtoupper(mb_substr($text, 0, 1));
        $src = base64_encode('<svg xmlns="http://www.w3.org/2000/svg" version="1.1" height="100" width="100"><rect fill="' . $bg . '" x="0" y="0" width="100" height="100"></rect><text x="50" y="50" font-size="50" text-copy="fast" fill="' . $color . '" text-anchor="middle" text-rights="admin" alignment-baseline="central">' . $first . '</text></svg>');
//        $value = 'data:image/svg+xml;base64,' . $src;
        $value = "data:image/svg+xml;base64," . $src;
        return $value;
    }


    public static function hsv2rgb($h, $s, $v)
    {
        $r = $g = $b = 0;

        $i = floor($h * 6);
        $f = $h * 6 - $i;
        $p = $v * (1 - $s);
        $q = $v * (1 - $f * $s);
        $t = $v * (1 - (1 - $f) * $s);

        switch ($i % 6) {
            case 0:
                $r = $v;
                $g = $t;
                $b = $p;
                break;
            case 1:
                $r = $q;
                $g = $v;
                $b = $p;
                break;
            case 2:
                $r = $p;
                $g = $v;
                $b = $t;
                break;
            case 3:
                $r = $p;
                $g = $q;
                $b = $v;
                break;
            case 4:
                $r = $t;
                $g = $p;
                $b = $v;
                break;
            case 5:
                $r = $v;
                $g = $p;
                $b = $q;
                break;
        }

        return [
            floor($r * 255),
            floor($g * 255),
            floor($b * 255)
        ];
    }


    public static function get_tree($a, $pid = 0)
    {
        $tree = array();                                //每次都声明一个新数组用来放子元素
        foreach ($a as $v) {
            if ($v['pid'] == $pid) {                      //匹配子记录
                $v['childlist'] = self::get_tree($a, $v['id']); //递归获取子记录
                if ($v['childlist'] == null) {
                    unset($v['childlist']);             //如果子元素为空则unset()进行删除，说明已经到该分支的最后一个元素了（可选）
                }
                $tree[] = $v;                           //将记录存入新数组
            }
        }
        return $tree;                                  //返回新数组
    }

    public static function fsget_tree($a, $pid = 0)
    {
        $tree = array();                                //每次都声明一个新数组用来放子元素
        foreach ($a as $v) {
            if ($v['pid'] == $pid) {                      //匹配子记录
                $v['childlist'] = self::fsget_tree($a, $v['category_id']); //递归获取子记录
                if ($v['childlist'] == null) {
                    unset($v['childlist']);             //如果子元素为空则unset()进行删除，说明已经到该分支的最后一个元素了（可选）
                }
                $tree[] = $v;                           //将记录存入新数组
            }
        }
        return $tree;                                  //返回新数组
    }


    public static function get_tree_my($array)
    {

        $new_data = [];

        foreach ($array as $v) {
            $new = [];
            $res = Db::table('category')->where('status', 1)->where('pid', $v->id)->first();
            if (empty($res)) {
                $new['childlist'] = [];
            }
            $new['id'] = $v->id;
            $new['pid'] = $v->pid;
            $new['name'] = $v->name;
            $new['nickname'] = $v->nickname;
            $new['icon'] = $v->icon;
            $new['flag'] = $v->flag;
            $new['image'] = $v->image;
            $new['keywords'] = $v->keywords;
            $new['description'] = $v->description;
            $new['createtime'] = $v->createtime;
            $new['updatetime'] = $v->updatetime;
            $new['weigh'] = $v->weigh;
            $new['status'] = $v->status;
            $new['scmproduct'] = $v->scmproduct;
            $new['scmbrands'] = $v->scmbrands;
            $new['arrparent_id'] = $v->arrparent_id;
            $new['fullimage'] = $v->fullimage;
            $new_data[] = $new;
        }

        //第一步 构造数据
        $items = array();
        foreach ($new_data as $value) {
            $items[$value['id']] = $value;
        }

        //第二部 遍历数据 生成树状结构
        $tree = array();
        foreach ($items as $key => $value) {
            if (isset($items[$value['pid']])) {
                $items[$value['pid']]['childlist'][] = &$items[$key];
            } else {
                $tree[] = &$items[$key];
            }
        }
        return $tree;
    }


    public static function yget_tree_my($array)
    {

        $new_data = [];

        foreach ($array as $v) {
            $new = [];
            $res = Db::table('ycategory')->where('status', 1)->where('pid', $v->id)->first();
            if (empty($res)) {
                $new['childlist'] = [];
            }
            $new['id'] = $v->id;
            $new['pid'] = $v->pid;
            $new['name'] = $v->name;
            $new['nickname'] = $v->nickname;
            $new['icon'] = $v->icon;
            $new['flag'] = $v->flag;
            $new['image'] = $v->image;
            $new['keywords'] = $v->keywords;
            $new['description'] = $v->description;
            $new['createtime'] = $v->createtime;
            $new['updatetime'] = $v->updatetime;
            $new['weigh'] = $v->weigh;
            $new['status'] = $v->status;
            $new['scmproduct'] = $v->scmproduct;
            $new['scmbrands'] = $v->scmbrands;
            $new['arrparent_id'] = $v->arrparent_id;
            $new['fullimage'] = $v->fullimage;
            $new_data[] = $new;
        }

        //第一步 构造数据
        $items = array();
        foreach ($new_data as $value) {
            $items[$value['id']] = $value;
        }

        //第二部 遍历数据 生成树状结构
        $tree = array();
        foreach ($items as $key => $value) {
            if (isset($items[$value['pid']])) {
                $items[$value['pid']]['childlist'][] = &$items[$key];
            } else {
                $tree[] = &$items[$key];
            }
        }
        return $tree;
    }


    public static function generateTree($array)
    {

        $new_data = [];

        foreach ($array as $v) {
            $new = [];
            $res = Db::table('category')->where('pid', $v->id)->first();
            if (empty($res)) {
                $new['childlist'] = [];
            }
            if ($v->pid == 0) {
                $productnum = Db::table('category')->whereRaw("FIND_IN_SET($v->id,arrparent_id)")->get();
                $a = count($productnum);
                $new['productnum'] = $a;
            }
            $new['id'] = $v->id;
            $new['pid'] = $v->pid;
            $new['name'] = $v->name;
            $new['nickname'] = $v->nickname;
            $new['icon'] = $v->icon;
            $new['flag'] = $v->flag;
            $new['image'] = $v->image;
            $new['keywords'] = $v->keywords;
            $new['description'] = $v->description;
            $new['createtime'] = $v->createtime;
            $new['updatetime'] = $v->updatetime;
            $new['weigh'] = $v->weigh;
            $new['status'] = $v->status;
            $new['scmproduct'] = $v->scmproduct;
            $new['scmbrands'] = $v->scmbrands;
            $new['arrparent_id'] = $v->arrparent_id;
            $new['fullimage'] = $v->fullimage;
            $new_data[] = $new;
        }

        //第一步 构造数据
        $items = array();
        foreach ($new_data as $value) {
            $items[$value['id']] = $value;
        }

        //第二部 遍历数据 生成树状结构
        $tree = array();
        foreach ($items as $key => $value) {
            if (isset($items[$value['pid']])) {
                $items[$value['pid']]['childlist'][] = &$items[$key];
            } else {
                $tree[] = &$items[$key];
            }
        }
        return $tree;
    }


    public static function ygenerateTree($array)
    {

        $new_data = [];

        foreach ($array as $v) {
            $new = [];
            $res = Db::table('ycategory')->where('pid', $v->id)->first();
            if (empty($res)) {
                $new['childlist'] = [];
            }
            if ($v->pid == 0) {
                $productnum = Db::table('ycategory')->whereRaw("FIND_IN_SET($v->id,arrparent_id)")->get();
                $a = count($productnum);
                $new['productnum'] = $a;
            }
            $new['id'] = $v->id;
            $new['pid'] = $v->pid;
            $new['name'] = $v->name;
            $new['nickname'] = $v->nickname;
            $new['icon'] = $v->icon;
            $new['flag'] = $v->flag;
            $new['image'] = $v->image;
            $new['keywords'] = $v->keywords;
            $new['description'] = $v->description;
            $new['createtime'] = $v->createtime;
            $new['updatetime'] = $v->updatetime;
            $new['weigh'] = $v->weigh;
            $new['status'] = $v->status;
            $new['scmproduct'] = $v->scmproduct;
            $new['scmbrands'] = $v->scmbrands;
            $new['arrparent_id'] = $v->arrparent_id;
            $new['fullimage'] = $v->fullimage;
            $new_data[] = $new;
        }

        //第一步 构造数据
        $items = array();
        foreach ($new_data as $value) {
            $items[$value['id']] = $value;
        }

        //第二部 遍历数据 生成树状结构
        $tree = array();
        foreach ($items as $key => $value) {
            if (isset($items[$value['pid']])) {
                $items[$value['pid']]['childlist'][] = &$items[$key];
            } else {
                $tree[] = &$items[$key];
            }
        }
        return $tree;
    }

    /**
     * 创建用户邀请码
     * @param $user_id
     * @return string
     */
    public static function createCode($user_id)
    {

        static $source_string = 'E5FCDG3HQA4B1NOPIJ2RSTUV67MWX89KLYZ';

        $num = $user_id;

        $code = '';

        while ($num > 0) {

            $mod = $num % 35;

            $num = ($num - $mod) / 35;

            $code = $source_string[$mod] . $code;

        }

        if (empty($code[3]))

            $code = str_pad($code, 4, '0', STR_PAD_LEFT);

        return $code;

    }


    /**
     * 解密邀请码
     * @param $code
     * @return float|int
     */
    public static function decode($code)
    {

        static $source_string = 'E5FCDG3HQA4B1NOPIJ2RSTUV67MWX89KLYZ';

        if (strrpos($code, '0') !== false)

            $code = substr($code, strrpos($code, '0') + 1);

        $len = strlen($code);

        $code = strrev($code);

        $num = 0;

        for ($i = 0; $i < $len; $i++) {

            $num += strpos($source_string, $code[$i]) * pow(35, $i);

        }

        return $num;

    }


    public static function request_by_curl($remote_server, $post_string, $type = 1)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $remote_server);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        if ($type == 2) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
        } else {
            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json;charset=utf-8'));
        }
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        // 线下环境不用开启curl证书验证, 未调通情况可尝试添加该代码
        // curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
        // curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }

    public static function getUrl($url, $header = false)
    {
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //返回数据不直接输出
        curl_setopt($ch, CURLOPT_ENCODING, "gzip"); //指定gzip压缩
        //add header
        if (!empty($header)) {
            curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        }
        //add ssl support
        if (substr($url, 0, 5) == 'https') {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);    //SSL 报错时使用
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);    //SSL 报错时使用
        }
        $content = curl_exec($ch); //执行并存储结果
        curl_close($ch);
        return $content;
    }


    /**
     * 获取分
     * @param float $money
     * @return int
     */
    public static function yuan2fen(float $money): int
    {
        return (int)($money * 100);
    }


    /**
     * 获取元
     * @param int $money
     * @return float
     */
    public static function fen2yuan(int $money): float
    {
        return (float)sprintf('%.2f', (int)$money / 100);
    }


    /**
     * 获取剩余时长（天、周、月、年）
     * @param int $end_time
     * @param string $unit
     * @return float $duration 精确到微秒
     */
    public static function get_to_end_duration(int $end_time, string $unit): float
    {
        switch ($unit) {
            case "year":
                $duration = Carbon::now()->floatDiffInYears(date('Y-m-d H:i:s', $end_time), false);
                break;
            case "day":
                $duration = Carbon::now()->floatDiffInDays(date('Y-m-d H:i:s', $end_time), false);
                break;
            case "month":
                $duration = Carbon::now()->floatDiffInMonths(date('Y-m-d H:i:s', $end_time), false);
                break;
            case "week":
                $duration = Carbon::now()->floatDiffInWeeks(date('Y-m-d H:i:s', $end_time), false);
                break;
            default:
                return 0.00;
        }
        return $duration;
    }

    /**
     * 格式化秒数为： 日-小时-分
     * @param int $sec
     * @return array
     */
    public static function formatSecondDuration(int $sec): array
    {
        $day = floor($sec / 86400);// 天
        $hour = floor(($sec / 86400 - $day) * 24);// 小时
        $min = floor((($sec / 86400 - $day) * 24 - $hour) * 60);// 分
        return [
            'day' => $day,
            'hour' => $hour,
            'min' => $min
        ];
    }


    /**
     * 获取树形结构
     * @param array $array
     * @param string $pid_key
     * @param string $id_key
     * @param string $children_key
     * @param null $callback
     * @return array
     */
    public static function generate_tree(array $array, $pid_key = 'pid', $id_key = 'id', $children_key = 'children', $callback = null)
    {
        if (!$array) {
            return [];
        }
        //第一步 构造数据
        $items = [];
        foreach ($array as $value) {
            if ($callback && is_callable($callback)) {
                $callback($value);
            }
            $items[$value[$id_key]] = $value;
        }
        //第二部 遍历数据 生成树状结构
        $tree = [];
        foreach ($items as $key => $value) {
            //如果pid这个节点存在
            if (isset($items[$value[$pid_key]])) {
                $items[$value[$pid_key]][$children_key][] = &$items[$key];
            } else {
                $tree[] = &$items[$key];
            }
        }
        return $tree;
    }

    /**
     * 根据IP地址获取用户所在城市
     * @param string $ip
     * @param string $algorithm
     * @param string $method
     * @return string
     */
    public static function getLocateByIp(string $ip, $algorithm = 'Memory', $method = 'memorySearch'): string
    {
        try {
            $dbFile = BASE_PATH . DS . 'public' . DS . 'ip2region.db';
            $ip2regionObj = new Ip2Region($dbFile);
            $data = $ip2regionObj->{$method}($ip);
            $return_str = "";
            if (!empty($data) && !empty($data['region'])) {
                $locate_arr = explode('|', $data['region']);
                if (!empty($locate_arr)) {
                    foreach ($locate_arr as $level => $r) {
                        if (!empty($r) && $level > 0 && $level < count($locate_arr) - 1) {
                            $return_str = $return_str . "-" . $r;
                        }
                    }
                }
            }
            return trim($return_str, '-');
        } catch (\Throwable $exception) {
            echo $exception->getMessage();
            return "未知IP";
        }
    }


    /**
     * 根据详细地址获取经纬度
     * @param string $addr_details
     * @return array ['lat'=>0,'lng'=>0]
     */
    public static function getAddressLocation(string $addr_details): array
    {
        if (empty($addr_details)) {
            return [];
        }
        try {
            $pos_res = file_get_contents("https://restapi.amap.com/v3/geocode/geo?key=094ab01ccbd3904b39729b94598d4099&address=" . $addr_details);
            if (empty($pos_res)) {
                return [];
            } else {
                $arr = json_decode($pos_res, true);
                if (empty($arr) || !isset($arr['geocodes']) || !isset($arr['geocodes'][0]) || !isset($arr['geocodes'][0]['location'])) {
                    return [];
                }
            }
            $loc = explode(',', $arr['geocodes'][0]['location']);
            return [
                'lat' => $loc[1],
                'lng' => $loc[0]
            ];
        } catch (\Throwable $exception) {
            echo $exception->getMessage();
            return [];
        }
    }

    /**
     * @param int $time
     * @return bool
     */
    public static function integerTimeCheck(int $time): bool
    {
        $time = (string)$time;
        if (strlen($time) <= 2) {
            if ($time <= 59) {
                return true;
            }
        } elseif (strlen($time) == 3) {
            if (substr($time, 1) <= 59) {
                return true;
            }
        } elseif (strlen($time) == 4) {
            if (substr($time, 0, 2) < 24 && substr($time, 2) <= 59) {
                return true;
            }
        }
        return false;
    }

    /**
     * @param $data
     * @return array
     */
    public static function address($data)
    {
        preg_match('/.*省/', $data, $provinces_arr);
        $data = preg_replace('/.*省/', '', $data);
        preg_match('/.*市/', $data, $city_arr);
        $data = preg_replace('/.*市/', '', $data);
        preg_match('/.*区/', $data, $region_arr);
        $data = preg_replace('/.*区/', '', $data);
        preg_match('/.*(街道|街)/', $data, $street_arr);
        if (count($provinces_arr) > 0) {
            $provinces_name = $provinces_arr[0];
        } else {
            $provinces_name = $city_arr[0];
        }
        if (count($city_arr) > 0) {
            $city_name = $city_arr[0];
        } else {
            $city_name = '无';
        }
        if (count($region_arr) > 0) {
            $region_name = $region_arr[0];
        } else {
            $region_name = '无';
        }
        if (count($street_arr) > 0) {
            $street_name = $street_arr[0];
        } else {
            $street_name = '无';
        }
        return compact('provinces_name', 'city_name', 'region_name', 'street_name');
    }

}